package net

import (
	"fmt"
	"giot/pkg/logger"
	"net"
	"strconv"
	"strings"
)

type UdpServer struct {
	Ip      string
	Port    int
	running bool

	dataArrival func(clientId string, data []byte)
	u           *net.UDPConn
}

func (s *UdpServer) Start(localIp string, localPort int) error {
	addr := net.UDPAddr{IP: net.ParseIP(localIp), Port: localPort}
	udp, err := net.ListenUDP("udp", &addr)
	if err != nil {
		return err
	}
	s.u = udp
	s.running = true
	go func() {
		for s.running {
			var d = make([]byte, BuffSize)
			n, r, err2 := s.u.ReadFrom(d)
			if err2 != nil {
				logger.GetLog().ErrorX(err2)
			} else {
				if s.dataArrival != nil {
					s.dataArrival(r.String(), d[:n])
				}
			}
		}
	}()

	return nil
}

// Stop 停止服务
func (s *UdpServer) Stop() {
	s.running = false
	if s.u != nil {
		_ = s.u.Close()
	}
	s.u = nil
}

// OnDataArrival 数据到达回调
// clientId 客户端id
// data 数据
func (s *UdpServer) OnDataArrival(f func(clientId string, data []byte)) {
	s.dataArrival = f
}

// OnClientConnected 客户端链接成功
func (s *UdpServer) OnClientConnected(func(clientId string, conn net.Conn)) {
	logger.GetLog().Errorf("UPD协议中方法无效")
}

// OnClientStateChange 客户端状态变化回调
// clientId 客户端id
// client 客户端
// state 状态
func (s *UdpServer) OnClientStateChange(func(clientId string, state ConnectState)) {
	logger.GetLog().Errorf("UPD协议中方法无效")
}

// Send 发送数据到客户端
// clientId 信息接收端的地址端口，格式:ip:port
// data:发送数据
func (s *UdpServer) Send(clientId string, data []byte) (int, error) {
	a := new(net.UDPAddr)
	split := strings.Split(clientId, ":")
	if len(split) != 2 {
		return 0, fmt.Errorf("远程服务器地址格式错误")
	}
	port, err2 := strconv.Atoi(split[1])
	if err2 != nil {
		return 0, err2
	}
	a.Port = port
	a.IP = net.ParseIP(split[0])
	n, err := s.u.WriteTo(data, a)
	return n, err
}

// Close 关闭客户端
func (s *UdpServer) Close(clientId string) {
	logger.GetLog().Errorf("UPD协议中方法无效")
}
